# === 必须替换的配置 ===
WIFI_SSID = "Redmi Note 12 5G"         
WIFI_PASSWORD = "dtp6pcf83jsvu92"  
PRODUCT_KEY = "k25es2SPWFj"              
DEVICE_NAME = "device1"              
DEVICE_SECRET = "a77ec4208402ed2e36e6a1efa9ae69ff"             
REGION = "cn-shanghai"                
# === 以上配置已修改 ===

from machine import Pin, SoftI2C, ADC, Timer
from ssd1306 import SSD1306_I2C
import dht
import time
import network
import json
import ubinascii
import hashlib
from umqtt.simple import MQTTClient

# === 修改点1：上报间隔常量定义 ===
REPORT_INTERVAL = 60000  

# === 修复后的HMAC-SHA1实现 ===
def hmac_sha1(key, msg):
    block_size = 64
    if len(key) > block_size:
        key = hashlib.sha1(key).digest()
    if len(key) < block_size:
        key += b'\x00' * (block_size - len(key))
    
    o_key_pad = bytes([x ^ 0x5c for x in key])
    i_key_pad = bytes([x ^ 0x36 for x in key])
    
    inner = hashlib.sha1(i_key_pad + msg).digest()
    outer = hashlib.sha1(o_key_pad + inner).digest()
    return outer

# === 硬件初始化 ===
SENSOR_PINS = {'dht':1, 'light':4, 'soil':5}
i2c = SoftI2C(sda=Pin(42), scl=Pin(40))
oled = SSD1306_I2C(128, 64, i2c, addr=0x3c)

def init_sensors():
    dht11 = dht.DHT11(Pin(SENSOR_PINS['dht']))
    time.sleep(2)  # 传感器初始化时间保持不变
    light = ADC(Pin(SENSOR_PINS['light']))
    light.atten(ADC.ATTN_11DB)
    soil = ADC(Pin(SENSOR_PINS['soil']))
    soil.atten(ADC.ATTN_11DB)
    return dht11, light, soil

# === 网络连接 ===
def connect_wifi():
    sta_if = network.WLAN(network.STA_IF)
    if not sta_if.isconnected():
        print("Connecting to WiFi...")
        sta_if.active(True)
        sta_if.connect(WIFI_SSID, WIFI_PASSWORD)
        while not sta_if.isconnected():
            time.sleep(0.5)
    print("WiFi Connected:", sta_if.ifconfig()[0])

def ali_signature():
    timestamp = str(int(time.time() * 1000))
    client_id = f"{DEVICE_NAME}|securemode=3,signmethod=hmacsha1,timestamp={timestamp}|"
    sign_content = f"clientId{DEVICE_NAME}deviceName{DEVICE_NAME}productKey{PRODUCT_KEY}timestamp{timestamp}"
    signature = hmac_sha1(
        DEVICE_SECRET.encode(),
        sign_content.encode()
    )
    return client_id, ubinascii.hexlify(signature).decode()

mqtt_client = None
def connect_mqtt():
    global mqtt_client
    client_id, signature = ali_signature()
    mqtt_client = MQTTClient(
        client_id=client_id,
        server=f"{PRODUCT_KEY}.iot-as-mqtt.{REGION}.aliyuncs.com",
        port=1883,
        user=f"{DEVICE_NAME}&{PRODUCT_KEY}",
        password=signature,
        keepalive=60  # 保持连接心跳间隔不变
    )
    mqtt_client.connect()
    print("MQTT Connected")

# === 数据上报 ===
def report_data(data):
    topic = f"/sys/{PRODUCT_KEY}/{DEVICE_NAME}/thing/event/property/post"
    payload = json.dumps({
        "id": int(time.time()),
        "params": {
            "temperature": float(data["temperature"]),
            "Humidity": float(data["Humidity"]),
            "LightLux": int(data["LightLux"]),
            "soilHumidity": int(data["soilHumidity"])
        },
        "method": "thing.event.property.post"
    })
    try:
        mqtt_client.publish(topic, payload)
        print("Published:", payload)
    except Exception as e:
        print("Publish Error:", e)
        connect_mqtt()

# === OLED显示 ===
def display_layout(data):
    oled.fill(0)
    oled.text('Real-time Monitor', 0, 0)
    oled.line(0, 12, 128, 12, 1)
    oled.text(f'T:{data["temperature"]:.1f}C', 0, 15)
    oled.text(f'H:{data["Humidity"]:.1f}%', 0, 30)
    oled.text(f'Lux:{data["LightLux"]}', 65, 15)
    oled.text(f'Soil:{data["soilHumidity"]}', 65, 30)
    status = "Normal" if data["temperature"] <=40 and data["Humidity"] <=80 else "Danger!"
    oled.text(status, 0, 45)
    oled.show()

# === 主循环 ===
def sensor_task(tim):
    try:
        d.measure()
        sensor_data = {
            "temperature": d.temperature(),
            "Humidity": d.humidity(),
            "LightLux": int(light.read() * 0.95),
            "soilHumidity": int(soil.read() * 1.08)
        }
        display_layout(sensor_data)
        report_data(sensor_data)
    except Exception as e:
        oled.fill(0)
        oled.text('Sensor Error!', 15, 30)
        oled.show()
        print("Error:", e)

# === 启动流程 ===
d, light, soil = init_sensors()
connect_wifi()
connect_mqtt()
tim = Timer(1)
# === 修改点2：定时器间隔调整为10秒 ===
tim.init(period=REPORT_INTERVAL, mode=Timer.PERIODIC, callback=sensor_task)
sensor_task(None)  # 初始化立即执行一次
